/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "DiskDataPersistence.h"
#include "FusionStorageCleanFile.h"
#include "log/Log.h"
#include "common/Structs.h"
#include "common/JsonUtils.h"

namespace {
const std::string MODULE_NAME = "FusionStorageVolumeHandler";
}

VIRT_PLUGIN_NAMESPACE_BEGIN

DiskDataPersistence::DiskDataPersistence()
{
    m_cleanFile = std::make_shared<FusionStorageCleanFile>();
    m_cacheUUID = boost::uuids::to_string(boost::uuids::random_generator()());
    m_cachedObjects[FusionStorageDef::CACHE_UUID] = m_cacheUUID;
}

DiskDataPersistence::~DiskDataPersistence()
{}

void DiskDataPersistence::AddObject(const std::string &key, const std::string &value)
{
    m_cachedObjects[key] = value;
    ChangeDiskDataPersistence();
}

void DiskDataPersistence::RemoveObject(const std::string &key)
{
    Json::Value removed;
    (void)m_cachedObjects.removeMember(key, &removed);
    ChangeDiskDataPersistence();
}

std::string DiskDataPersistence::GetObject(const std::string &key)
{
    std::string value;
    if (m_cachedObjects.isMember(key) && m_cachedObjects[key].isString()) {
        value = m_cachedObjects[key].asString();
    }
    return value;
}

void DiskDataPersistence::AppendArrayElement(const std::string &key, const std::string &value)
{
    (void)m_cachedObjects[key].append(value);
    ChangeDiskDataPersistence();
}

void DiskDataPersistence::RemoveArrayElement(const std::string &key, const std::string &value)
{
    Json::Value obj;
    for (uint32_t i = 0; i < m_cachedObjects[key].size(); i++) {
        if (!m_cachedObjects[key][i].isNull() && m_cachedObjects[key][i].isString() &&
            m_cachedObjects[key][i].asString() != value) {
            obj.append(m_cachedObjects[key][i]);
        } else if (!m_cachedObjects[key][i].isNull() && m_cachedObjects[key][i].isObject() &&
                   m_cachedObjects[key][i]["key"].asString() != value) {
            obj.append(m_cachedObjects[key][i]);
        }
    }

    Json::Value removed;
    m_cachedObjects.removeMember(key, &removed);
    m_cachedObjects[key] = obj;
    ChangeDiskDataPersistence();
}

std::string DiskDataPersistence::GetFirstArrayElement(const std::string &key)
{
    std::string value;
    if (m_cachedObjects[key].isArray() && m_cachedObjects[key].size() > 0) {
        try {
            value = m_cachedObjects[key][0].asString();
        } catch (std::exception &e) {
            ERRLOG("Get array element failed. Exception is %s.", e.what());
            value.clear();
        }
    }
    return value;
}

bool DiskDataPersistence::ToJsonValue(const std::string &jsonStr)
{
    bool ret = Module::CJsonUtils::ConvertStringtoJson(jsonStr, m_cachedObjects);
    if (ret && m_cachedObjects.isMember(FusionStorageDef::CACHE_UUID)) {
        m_cacheUUID = m_cachedObjects[FusionStorageDef::CACHE_UUID].asString();
    }
    return ret;
}

std::string DiskDataPersistence::ToJsonString()
{
    std::string str = Module::CJsonUtils::ConvertJsonToString(m_cachedObjects);
    if (str.size() > 0 && str.at(str.size() - 1) == '\n') {
        str = str.substr(0, str.size());
    }
    return Module::CJsonUtils::ConvertJsonToString(m_cachedObjects);
}

std::string DiskDataPersistence::GetCachedUUID()
{
    return m_cacheUUID;
}

void DiskDataPersistence::Finish()
{
    if (IsCachedataUsefull()) {
        m_cleanFile->AddOrReplaceItem(m_cacheUUID, ToJsonString(), false);
    }
}

bool DiskDataPersistence::IsCachedataUsefull()
{
    bool bUsefull = !m_cachedObjects[FusionStorageDef::SNAPSHOT_VOLUMES_ATTACHED].isNull() ||
        m_cachedObjects[FusionStorageDef::SNAPSHOT_VOLUMES_ATTACHED].size() > 0;
    if (bUsefull) {
        return true;
    }

    bUsefull = !m_cachedObjects[FusionStorageDef::BITMAP_VOLUMES_CREATED].isNull() ||
        m_cachedObjects[FusionStorageDef::BITMAP_VOLUMES_CREATED].size() > 0;
    if (bUsefull) {
        return true;
    }

    bUsefull = !m_cachedObjects[FusionStorageDef::BITMAP_VOLUMES_ATTACHED].isNull() ||
        m_cachedObjects[FusionStorageDef::BITMAP_VOLUMES_ATTACHED].size() > 0;
    if (bUsefull) {
        return true;
    }

    bUsefull = !m_cachedObjects[FusionStorageDef::DATA_VOLUMES_ATTACHED].isNull() ||
        m_cachedObjects[FusionStorageDef::DATA_VOLUMES_ATTACHED].size() > 0;
    if (bUsefull) {
        return true;
    }

    return false;
}

void DiskDataPersistence::ChangeDiskDataPersistence()
{
    if (IsCachedataUsefull()) {
        m_cleanFile->AddOrReplaceItem(m_cacheUUID, ToJsonString());
    } else {
        m_cleanFile->RemoveItem(m_cacheUUID);
    }
}

VIRT_PLUGIN_NAMESPACE_END
